/* Copyright (C) 2005-2013, Unigine Corp. All rights reserved.
 *
 * File:    vertex_base_velocity.h
 * Desc:    Mesh base velocity shader
 * Version: 1.04
 * Author:  Alexander Zapryagaev <frustum@unigine.com>
 *
 * This file is part of the Unigine engine (http://unigine.com/).
 *
 * Your use and or redistribution of this software in source and / or
 * binary form, with or without modification, is subject to: (i) your
 * ongoing acceptance of and compliance with the terms and conditions of
 * the Unigine License Agreement; and (ii) your inclusion of this notice
 * in any version of this software that you use or redistribute.
 * A copy of the Unigine License Agreement is available by contacting
 * Unigine Corp. at http://unigine.com/
 */

/******************************************************************************\
*
* OpenGL
*
\******************************************************************************/

#ifdef OPENGL
	
	#ifndef VERTEX_BASE_VELOCITY
		#define VERTEX_BASE_VELOCITY
		
		#ifdef MESH_SKINNED && !USE_TRANSFORMING
			UNIFORM_BUFFER_BEGIN(shader_mesh_velocity_parameters)
				uniform float4 s_mesh_velocities[192];
			UNIFORM_BUFFER_END
		#else
			uniform float3 s_mesh_center_of_mass;
			uniform float3 s_mesh_linear_velocity;
			uniform float3 s_mesh_angular_velocity;
		#endif
		
	#else
		
		gl_Position = getPosition(vertex);
		
		s_texcoord_0 = texcoord;
		
		#ifdef MESH_SKINNED && !USE_TRANSFORMING
			
			float3 velocity;
			
			bones = (bones / 2) * 3;
			
			#define SKINNING(SWIZZLE,OP) { \
				float4 center_of_mass = float4(s_mesh_velocities[bones.SWIZZLE].xyz,1.0f); \
				float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass)); \
				velocity OP (s_mesh_velocities[bones.SWIZZLE + 1].xyz + cross(s_mesh_velocities[bones.SWIZZLE + 2].xyz,vertex_direction)) * weights.SWIZZLE; \
			}
			
			SKINNING(x,=)
			SKINNING(y,+=)
			SKINNING(z,+=)
			SKINNING(w,+=)
			
			#undef SKINNING
			
		#else
			
			float4 center_of_mass = float4(s_mesh_center_of_mass,1.0f);
			float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass));
			float3 velocity = s_mesh_linear_velocity + cross(s_mesh_angular_velocity,mul3(s_imodelview,vertex_direction));
			
		#endif
		
		s_texcoord_1 = float4(velocity * 0.5f + 127.0f / 255.0f,1.0f);
		
		#ifdef USE_TESSELLATION && TESSELLATION
			
			#ifdef USE_ALPHA_FADE && ALPHA_FADE
				gl_Position.w = getAlphaFade(bound_sphere);
			#endif
			
		#else
			
			#ifdef USE_ALPHA_FADE && ALPHA_FADE
				s_texcoord_9.x = getAlphaFade(bound_sphere);
			#endif
			
		#endif
		
	#endif
	
/******************************************************************************\
*
* Direct3D11
*
\******************************************************************************/

#elif DIRECT3D11
	
	#ifndef VERTEX_BASE_VELOCITY
		#define VERTEX_BASE_VELOCITY
		
		struct VERTEX_OUT {
			float4 position : OUT_POSITION;
			float4 texcoord_0 : TEXCOORD0;
			float4 texcoord_1 : TEXCOORD1;
			#ifdef USE_TESSELLATION && TESSELLATION
				float4 texcoord_9 : TEXCOORD9;
			#else
				#ifdef USE_ALPHA_FADE && ALPHA_FADE
					float1 texcoord_9 : TEXCOORD9;
				#endif
			#endif
		};
		
		#ifdef MESH_SKINNED && !USE_TRANSFORMING
			cbuffer shader_mesh_velocity_parameters {
				float4 s_mesh_velocities[192];
			};
		#else
			cbuffer shader_velocity_parameters {
				float3 s_mesh_center_of_mass;
				float3 s_mesh_linear_velocity;
				float3 s_mesh_angular_velocity;
			};
		#endif
		
	#else
		
		OUT.position = getPosition(vertex);
		
		OUT.texcoord_0 = texcoord;
		
		#ifdef MESH_SKINNED && !USE_TRANSFORMING
			
			float3 velocity;
			
			bones = (bones >> 1) * 3;
			
			#define SKINNING(SWIZZLE,OP) { \
				float4 center_of_mass = float4(s_mesh_velocities[bones.SWIZZLE].xyz,1.0f); \
				float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass)); \
				velocity OP (s_mesh_velocities[bones.SWIZZLE + 1].xyz + cross(s_mesh_velocities[bones.SWIZZLE + 2].xyz,vertex_direction)) * weights.SWIZZLE; \
			}
			
			SKINNING(x,=)
			SKINNING(y,+=)
			SKINNING(z,+=)
			SKINNING(w,+=)
			
			#undef SKINNING
			
		#else
			
			float4 center_of_mass = float4(s_mesh_center_of_mass,1.0f);
			float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass));
			float3 velocity = s_mesh_linear_velocity + cross(s_mesh_angular_velocity,mul3(s_imodelview,vertex_direction));
			
		#endif
		
		OUT.texcoord_1 = float4(velocity * 0.5f + 127.0f / 255.0f,1.0f);
		
		#ifdef USE_TESSELLATION && TESSELLATION
			
			#ifdef USE_ALPHA_FADE && ALPHA_FADE
				OUT.position.w = getAlphaFade(bound_sphere);
			#endif
			
		#else
			
			#ifdef USE_ALPHA_FADE && ALPHA_FADE
				OUT.texcoord_9.x = getAlphaFade(bound_sphere);
			#endif
			
		#endif
		
	#endif
	
/******************************************************************************\
*
* Direct3D9
*
\******************************************************************************/

#elif DIRECT3D9
	
	#ifndef VERTEX_BASE_VELOCITY
		#define VERTEX_BASE_VELOCITY
		
		struct VERTEX_OUT {
			float4 position : POSITION;
			float4 texcoord_0 : TEXCOORD0;
			float4 texcoord_1 : TEXCOORD1;
			#ifdef USE_ALPHA_FADE && ALPHA_FADE
				float4 texcoord_7 : TEXCOORD7;
			#endif
		};
		
		#ifdef MESH_SKINNED && !USE_TRANSFORMING
			float4 s_mesh_velocities[192];
		#else
			float3 s_mesh_center_of_mass;
			float3 s_mesh_linear_velocity;
			float3 s_mesh_angular_velocity;
		#endif
		
	#else
		
		OUT.position = getPosition(vertex);
		
		OUT.texcoord_0 = texcoord;
		
		#ifdef MESH_SKINNED && !USE_TRANSFORMING
			
			float3 velocity;
			
			bones = (bones / 2) * 3;
			
			#define SKINNING(SWIZZLE,OP) { \
				float4 center_of_mass = float4(s_mesh_velocities[bones.SWIZZLE].xyz,1.0f); \
				float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass)); \
				velocity OP (s_mesh_velocities[bones.SWIZZLE + 1].xyz + cross(s_mesh_velocities[bones.SWIZZLE + 2].xyz,vertex_direction)) * weights.SWIZZLE; \
			}
			
			SKINNING(x,=)
			SKINNING(y,+=)
			SKINNING(z,+=)
			SKINNING(w,+=)
			
			#undef SKINNING
			
		#else
			
			float4 center_of_mass = float4(s_mesh_center_of_mass,1.0f);
			float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass));
			float3 velocity = s_mesh_linear_velocity + cross(s_mesh_angular_velocity,mul3(s_imodelview,vertex_direction));
			
		#endif
		
		OUT.texcoord_1 = float4(velocity * 0.5f + 127.0f / 255.0f,1.0f);
		
		#ifdef USE_ALPHA_FADE && ALPHA_FADE
			OUT.texcoord_7 = getProjection(OUT.position);
			OUT.texcoord_7.z = getAlphaFade(bound_sphere);
		#endif
		
	#endif
	
/******************************************************************************\
*
* PlayStation3
*
\******************************************************************************/

#elif PLAYSTATION3
	
	#ifndef VERTEX_BASE_VELOCITY
		#define VERTEX_BASE_VELOCITY
		
		struct VERTEX_OUT {
			float4 position : POSITION;
			float4 texcoord_0 : TEXCOORD0;
			float4 texcoord_1 : TEXCOORD1;
			#ifdef USE_ALPHA_FADE && ALPHA_FADE
				float4 texcoord_9 : TEXCOORD9;
			#endif
		};
		
		uniform float3 s_mesh_center_of_mass;
		uniform float3 s_mesh_linear_velocity;
		uniform float3 s_mesh_angular_velocity;
		
	#else
		
		OUT.position = getPosition(vertex);
		
		OUT.texcoord_0 = texcoord;
		
		float4 center_of_mass = float4(s_mesh_center_of_mass,1.0f);
		float3 vertex_direction = vertex.xyz - float3(dot(row_0,center_of_mass),dot(row_1,center_of_mass),dot(row_2,center_of_mass));
		float3 velocity = s_mesh_linear_velocity + cross(s_mesh_angular_velocity,mul3(s_imodelview,vertex_direction));
		
		OUT.texcoord_1 = float4(velocity * 0.5f + 127.0f / 255.0f,1.0f);
		
		#ifdef USE_ALPHA_FADE && ALPHA_FADE
			OUT.texcoord_9 = getProjection(OUT.position);
			OUT.texcoord_9.z = getAlphaFade(bound_sphere);
		#endif
		
	#endif
	
#endif
